package com.universal.exception;

import com.universal.base.resp.ApiResult;
import com.universal.common.enums.ErrorCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * 全局异常处理器
 *
 * @author: austin
 * @since: 2022/12/20 20:09
 */
@Slf4j
@RestControllerAdvice
public class GlobalBusinessExceptionHandler {

    @ExceptionHandler(value = MissingServletRequestParameterException.class)
    public ApiResult missingServletRequestParameterException(Exception e) {
        log.error("missingServletRequestParameterException error:{},{}", e.getMessage(), e);
        return ApiResult.failure(e.getMessage(), ErrorCode.ERR_20000.getCode());
    }


    @ExceptionHandler(GlobalBusinessException.class)
    public ApiResult handleGlobalException(GlobalBusinessException e) {
        log.error(e.getMessage(), e);
        return ApiResult.failure(e.getMessage());
    }

    @ExceptionHandler(value = InvalidParamException.class)
    public ApiResult<?> invalidParamHandler(InvalidParamException e) {
        log.error("InvalidParamException:{}", e);
        return ApiResult.failure("param invalid");
    }


    @ExceptionHandler(value = {MethodArgumentNotValidException.class, BindException.class})
    public ApiResult<?> methodArgumentNotValidExceptionHandler(HttpServletRequest request, Exception exception) {
        BindingResult result = null;
        if (exception instanceof MethodArgumentNotValidException) {
            result = ((MethodArgumentNotValidException) exception).getBindingResult();
        } else if (exception instanceof BindException) {
            result = ((BindException) exception).getBindingResult();
        } else {
            return ApiResult.failure("sys.program.error");
        }
        StringBuilder sb = new StringBuilder();
        if (result.hasErrors()) {
            List<FieldError> fieldErrors = result.getFieldErrors();
            fieldErrors.forEach(error -> {
                sb.append("field:" + error.getField() + ", msg:" + error.getDefaultMessage()).append(",");
            });
        }
        if (sb.length() > 0) {
            sb.setLength(sb.length() - 1);
        }
        String msg = sb.toString();
        log.error("exception occur, uri:{}, detail:{} ", request.getRequestURI(), msg);
        return ApiResult.failure(msg);
    }


}
